<?php

namespace App\Http\Controllers\Api;

use App\Exceptions\ResponseException;
use App\Jobs\AutoClearOrder;
use App\Models\Cart;
use App\Models\CouponRelationGoods;
use App\Models\Goods;
use App\Models\GoodsSku;
use App\Models\Order;
use App\Models\OrderInfo;
use App\Models\SpecValue;
use App\Models\UserAddress;
use App\Models\UserCoupons;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Redis;
use Whoops\Exception\ErrorException;

class CartController extends Controller
{
	/**
	 * 显示购物车商品
	 * User: Clannad ~ ☆
	 * DataTime：2019/11/17 0017 19:31
	 */
	public function index()
	{
		$cart = Cart::query()
			->select('cart.id', 'user_id', 'goods_id', 'number', 'cart.price', 'goods.goods_name', 'goods.thumb','sku_list', 'cart.created_at')
			->leftJoin('goods','cart.goods_id','=','goods.id')
			->where('user_id', auth('api')->id())
			->get()->toArray();

		if (count($cart) > 0) {
			foreach ($cart as $k => $v) {
				$sku = SpecValue::query()
					->select('value', 'spec.spec_name')
					->leftJoin('spec', 'spec.id', '=', 'spec_value.spec_id')
					->whereIn('spec_value.id', explode(',', $v['sku_list']))
					->get()->toArray();

				$cart[$k]['sku_info'] = $sku;
			}

			throw new ResponseException(200, 'ok', $cart);
		} else {
			throw new ResponseException(404, '购物车中没有商品');
		}
	}


	/**
	 * 加入购物车
	 * User: Clannad ~ ☆
	 * DataTime：2019/11/17 0017 19:44
	 * @param Request $request
	 * @throws ResponseException
	 */
	public function store(Request $request)
	{
		//加入购物车逻辑  如果没有该商品，就直接加入，如果有该商品，就进行数量累加
		$cartData = $request->all();

		$goods = Goods::find($cartData['goods_id']);

		if ( ! $goods) {
			throw new ResponseException(404, '商品不存在');
		}

		//查询sku
		$sku = GoodsSku::query()
			->where([
				'goods_id' => $cartData['goods_id'],
				'sku_list' => $cartData['sku_list'],
			])
			->where('inventory', '>', '0')
			->where('price', '>', '0')
			->first();

		if ( ! $sku) {
			throw new ResponseException(400, '页面已过期，请重新刷新页面后重试');
		}

		//查询当前规格的商品是否已经加入购物车
		$cart = Cart::query()->where([
			'goods_id' => $cartData['goods_id'],
			'user_id'  => auth('api')->id(),
			'sku_list' => $cartData['sku_list']
		])
			->first();

		if ($cart) {
			//累加数量
			$cart->increment('number', $cartData['number']);
			throw new ResponseException(200, '添加购物车成功');
		} else {
			//新增
			$cart = Cart::create([
				'goods_id'   => $cartData['goods_id'],
				'user_id'    => auth('api')->id(),
				'sku_list'   => $cartData['sku_list'],
				'number'     => $cartData['number'],
				'price'      => $sku['price'],
			]);

			if ($cart->id) {
				throw new ResponseException(200, '添加购物车成功');
			} else {
				throw new ResponseException(500, '添加失败，请联系管理员');
			}
		}

	}

	/**
	 * 购物车结算页
	 * User: Clannad ~ ☆
	 * DataTime：2019/11/18 0018 15:04
	 */
	public function settlement(Request $request)
	{
		//获取结算的购物车id
		$cartIds = $request->input('cart_ids');//1,2,3,4 这种形式的购物车id
		$cartIds = explode(',', $cartIds);

		//查询购物车
		$cartList = Cart::query()
			->select('cart.id', 'user_id', 'cart.goods_id', 'cart.number', 'cart.price as cart_price', 'goods.goods_name','goods.thumb','cart.sku_list', 'cart.created_at','goods_sku.price')
			->leftJoin('goods','cart.goods_id','=','goods.id')
            ->leftJoin('goods_sku',function($query){
                $query->on('goods_sku.goods_id','=','cart.goods_id')->on('goods_sku.sku_list','=','cart.sku_list');
            })
			->whereIn('cart.id', $cartIds)
			->where('user_id', auth('api')->id())
			->get()->toArray();

		$total_price = 0;
		$cart_goods = [];
		if ($cartList) {
			foreach ($cartList as $k => $v) {
				$sku_info = SpecValue::query()
					->select('spec.spec_name', 'spec_value.value')
					->leftJoin('spec', 'spec.id', '=', 'spec_value.spec_id')
					->whereIn('spec_value.id', explode(',', $v['sku_list']))
					->get()->toArray();

				$cartList[$k]['sku_info'] = $sku_info;

				$total_price = bcadd(($v['price'] * $v['number']),$total_price,2);
                $cart_goods[$v['goods_id']] = $v['number'];
			}

			//查用户地址
			$user_address = auth('api')->user()->user_address()
				->select('user_address.id', 'user_id', 'username', 'tel', 'user_address.county_id',
                    \DB::raw('REPLACE(my_region.whole_name,",","") as area'),
                    'address', 'default')
                ->leftJoin('region','user_address.county_id','=','region.county_id')
                ->groupBy(['user_address.id'])
                ->orderBy('default','desc')
				->get()->toArray();

			//查询用户的优惠券
            $user_coupons = auth('api')->user()->coupons()
                        ->select('id','coupon_id','coupon_type','time_type','use_price','dec_price','discount')
                        ->with([
                            'coupon'=>function($query){
                                return $query->select('id','coupon_name');
                            }
                        ])
                        ->where([
                            'status'=>1
                        ])->get()->toArray();

            $can_use_coupons = [];
            if($user_coupons){
                foreach ($user_coupons as $k => $v) {
                    //优惠券类型 1.店铺满减 2.店铺折扣 3.通用满减 4.通用折扣 5.免邮 6.指定商品
                    if($v['coupon_type'] == 1){

                    }else if($v['coupon_type'] == 2){

                    }else if($v['coupon_type'] == 3 || $v['coupon_type'] == 4 || $v['coupon_type'] == 5){
                        if(bccompNum($total_price,'>',$v['use_price'])){ //有效
                            $can_use_coupons[] = $v;
                            continue;
                        }
                    }else if($v['coupon_type'] == 6){
                        //查询可以优惠的商品
                        $goods = CouponRelationGoods::query()
                            ->select('goods_id','numbers')
                            ->where([
                            'coupon_id'=>$v['coupon_id']
                        ])->first();
                        $goods_ids = array_keys($cart_goods);
                        if(in_array($goods['goods_id'],$goods_ids) && $cart_goods[$goods['goods_id']] >= $goods['numbers']){
                            $can_use_coupons[] = $v;
                        }
                    }
                }
            }

			$data = [
				'cart_list'    => $cartList,
				'user_address' => $user_address,
                'can_use_coupons'=>$can_use_coupons,//可使用的优惠券
			];
			throw new ResponseException(200, 'ok', $data);
		} else {
			throw new ResponseException(404, '未找到购物车中的商品');
		}
	}


	/**
	 * 确认生成订单
	 * User: Clannad ~ ☆
	 * DataTime：2019/11/18 0018 16:09
	 * @param Request $request
	 * @param $id
	 */
	public function confirmOrder(Request $request)
	{
		//用户地址id
		//购物车ids
		$user_addr_id = $request->input('user_addr_id');
		$cart_ids     = $request->input('cart_ids');
		$express_type     = $request->input('express_type');
		$remark       = $request->input('remark');
		$coupon_id       = $request->input('coupon_id');

		$cartList = Cart::query()
					->whereIn('id', explode(',', $cart_ids))
					->where('user_id', auth('api')->id())
					->get()->toArray();

		if ( ! $cartList) {
			throw new ResponseException(404, '未找到需要结算的商品');
		}

		//用户地址
		$user_address = UserAddress::find($user_addr_id);

		if ( ! $user_address) {
			throw new ResponseException(404, '用户地址不存在');
		}

		$order_sn = createUniqueOrderSn();
		$order    = [
            'order_sn'     => $order_sn,
            'user_id'      => auth('api')->id(),
            'province_id'  => $user_address['province_id'],
            'city_id'      => $user_address['city_id'],
            'county_id'    => $user_address['county_id'],
            'address'      => $user_address['address'],
            'username'     => $user_address['username'],
            'tel'          => $user_address['tel'],
            'remark'       => $remark,
            'express_type' => $express_type,
            'coupon_id'    => $coupon_id ?? 0
		];

		\DB::beginTransaction();
		try{
			//插入订单
			$order_id = Order::create($order);

			if ($order_id->id) {
				//循环购物车，加入商品订单详情
				$price_total = 0;
				$goods_total = 0;

				//商品库存总数
				$goodsInventroy = [];

				foreach ($cartList as $k => $v) {

					if(isset($goodsInventroy[$v['goods_id']])){
						$goodsInventroy[$v['goods_id']] += $v['number'];
					}else{
						$goodsInventroy[$v['goods_id']] = $v['number'];
					}

					//获取商品名
					$goods = Goods::query()
						->select('goods_name','thumb','kill_status','id')
						->where([
							'status'=>1,
                            'id'=>$v['goods_id']
						])
						->first();

					if( ! $goods){
						\DB::rollBack();
						throw new ResponseException(400,'购物车中有下架或不存在的商品，订单确认失败');
					}

					//获取sku信息，并减少库存 行锁（悲观锁）
					$goods_sku = GoodsSku::query()->where([
					    'sku_list'=>$v['sku_list'],
                        'goods_id'=>$v['goods_id']
                        ])->lockForUpdate()->first();

					if( ! $goods_sku){
						\DB::rollBack();
						throw new ResponseException(404,'商品规格不存在');
					}

					//判断库存是否足够
					if($goods_sku['inventory'] < $v['number']){
						\DB::rollBack();
						throw new ResponseException(400,'【' . $goods['goods_name'] . '】库存不足，下单失败');
					}

					$order_info = [
						'order_id'=>$order_id->id,
						'order_sn'=>$order_sn,
						'goods_id'=>$v['goods_id'],
						'goods_name'=>$goods['goods_name'],
						'thumb'=>$goods['thumb'],
						'sku_list'=>$v['sku_list'],
						'number'=>$v['number'],
						'price'=>$goods_sku['price'],//使用最新的sku价格 参照淘宝机制
					];

					$price_total = bcadd(bcmul($v['number'],$goods_sku['price'],2),$price_total,2);
					$goods_total += $v['number'];

					//插入订单
					$res = OrderInfo::create($order_info);

					if($res->id){
						//减库存  -》 已改成付款减库存
						$newInventory = $goods_sku['inventory'] - $v['number'];
						$goods_sku->update(['inventory'=>$newInventory]);

                        //如果商品的秒杀状态是1 那么还要减秒杀hash表的内容
                        if($goods->kill_status == 1){
                            $seckill_id = $goods->seckill_goods()->where(['kill_status'=>1])->value('id');
                            $key = 'goods_sku_stock:goods_id:'.$v['goods_id'].':active_id:'.$seckill_id;

                            $old_inventory = Redis::hget($key,$v['sku_list']);
                            $new_inventory = $old_inventory - $v['number'];
                            Redis::hset($key,$v['sku_list'],$new_inventory);
                        }
						//清理购物车
						Cart::query()->where('id',$v['id'])->delete();
					}else{
						\DB::rollBack();
						throw new ResponseException(500,'下单失败，请联系管理员');
					}
				}

                $coupon_price = 0;
                $org_price_total = $price_total;
                $express_price = 8; //默认快递费为8
                $coupon_type = 0;

                $cart_goods = array_column($cartList,'number','goods_id');
                $goods_ids = array_keys($cart_goods);

                if($coupon_id){
                    $coupon = UserCoupons::query()->where(['id'=>$coupon_id])->first();

                    if ( ! $coupon) {
                        throw new ResponseException(400, '没有找到优惠券信息，下单失败');
                    }

                    //判断优惠券的类型 并计算价格
                    //优惠券类型 1.店铺满减 2.店铺折扣 3.通用满减 4.通用折扣 5.免邮 6.指定商品
                    if($coupon['coupon_type'] == 1){

                    }else if($coupon['coupon_type'] == 2){

                    }else if($coupon['coupon_type'] == 3){
                        if(bccompNum($price_total,'>',$coupon['use_price'])){
                            $coupon_price = $coupon['dec_price'];
                        }else{
                            throw new ResponseException(400,'优惠券金额校验有误，优惠券使用失败');
                        }
                    }else if($coupon['coupon_type'] == 4){
                        //判断是否满足折扣金额
                        if(bccompNum($price_total,'>',$coupon['use_price'])){
                            $dec_price = bcsub($price_total,bcmul($price_total,bcdiv($coupon['discount'],100,2),2),2);
                            $coupon_price = $dec_price;
                        }else{
                            throw new ResponseException(400,'优惠券金额校验有误，优惠券使用失败');
                        }
                    }else if($coupon['coupon_type'] == 5){
                        $express_price = 0;
                        $coupon_type = 5;
                    }else if($coupon['coupon_type'] == 6){
                        $goods = CouponRelationGoods::query()->select('goods_id','numbers')->where(['coupon_id'=>$coupon_id])->first();

                        if(in_array($goods['goods_id'],$goods_ids) && $cart_goods[$goods['goods_id']] >= $goods['numbers']){
                            $coupon_price = $coupon['dec_price'];
                        }else{
                            throw new ResponseException(400,'优惠券校验有误，优惠券使用失败');
                        }
                    }
                }

                if($coupon_price){
                    $price_total = bcsub($price_total,$coupon_price,2);//减去优惠券金额
                }

                //如果是快递配送，这里要加8元的运费
                if($express_type == 1 && $coupon_type != 5){
                    $price_total = bcadd($price_total,$express_price,2);
                }

				//更新总价格和总数量到总表
				$order_id->price_total = $price_total; //总价，喊优惠券和邮费
				$order_id->org_price_total = $org_price_total; //原价 不包含优惠券的价格
				$order_id->express_price = $express_price;
				$order_id->goods_total = $goods_total;
				$order_id->coupon_price = $coupon_price;

				//更新商品总表库存
				foreach ($goodsInventroy as $k => $v) {
				    $goods = Goods::query()->where(['id'=>$k])->lockForUpdate()->first();
				    $goods->decrement('inventory',$v); //使用共享锁减少库存

//                    $inventory = $goods->inventory - $v;
//                    $goods->save(['inventory'=>$inventory]); //使用共享锁减少库存

//                    \DB::table('goods')->where('id', '=', $k)->sharedLock()->get();

					//如果产品数量为0，下架
					if($goods->inventory == 0){
					    $goods->status = 0;
					    $goods->save();
					}
				}

				if($order_id->save()){

				    //将优惠券状态变更为已使用
                    if($coupon_id){
                        UserCoupons::query()->where(['id'=>$coupon_id])->update(['status'=>2]);
                    }

                    //派发延时任务，过期不付款自动取消订单
                    AutoClearOrder::dispatch($order_id->id,$order_sn)->delay(90);

				    \DB::commit();
				    throw new ResponseException(200,'下单成功',[
				        'order_sn'=>$order_sn,
                    ]);
				}else{
					\DB::rollBack();
					throw new ResponseException(500,'下单失败');
				}
			}else{
				\DB::rollBack();
				throw new ResponseException(500,'下单失败，请联系管理员');
			}
		}catch (ErrorException $exception){
			//此次可以做记录
			\Log::info('插入订单失败',$exception->getMessage());
			\DB::rollBack();
			throw new ResponseException(500,'订单确认失败，请稍后再试试');
		}
	}

	/**
	 * 删除购物车
	 *
	 * @param  int $id
	 * @return \Illuminate\Http\Response
	 */
	public function destroy(Request $request)
	{
		$id = $request->input();

		//判断购物车数据是否存在
        $checkCart = Cart::query()->where([
            'user_id'=>auth('api')->id(),
            'id'=>$id
        ])->first();

        if(!$checkCart){
            throw new ResponseException(404,'没有找到该购物车商品');
        }

        //删除购物车
        Cart::query()->where([
            'user_id'=>auth('api')->id(),
            'id'=>$id
        ])->delete();

        throw new ResponseException(200,'删除成功');
	}

    /**
     * 更改购物车数量
     * User: ihome
     */
    public function changeCartNumber(Request $request)
	{
	    $cart_id = $request->input('id');
	    $type = $request->input('type');

	    //判断购物车是否存在
        $checkCart = Cart::query()->where([
            'user_id'=>auth('api')->id(),
            'id'=>$cart_id
        ])->first();

        if(!$checkCart){
            throw new ResponseException(404,'没有找到该购物车商品');
        }

        if($type == 1){
            Cart::query()->where([
                'user_id'=>auth('api')->id(),
                'id'=>$cart_id
            ])->increment('number');
        }else{
            Cart::query()->where([
                'user_id'=>auth('api')->id(),
                'id'=>$cart_id
            ])->decrement('number');
        }

        throw new ResponseException(200,'操作成功');
	}

    /**
     * 检查用户收货地址是否设置 未设置不可提交订单
     * User: Clannad ~ ☆
     */
    public function checkAddrCount()
	{
        $count = UserAddress::query()->where([
            'user_id'=>auth('api')->id(),
            'default'=>1
        ])->count();

        if($count){
            throw new ResponseException(200,'ok');
        }else{
            throw new ResponseException(400,'您尚未设置收货地址');
        }
	}
}
